00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <inttypes.h>
00026 #include <avr/io.h>
00027 #include <avr/pgmspace.h>
00028 #include "lcd.h"
00029
00030
00031
00032
00033
00034
00035 #define DDR(x) (*(&x - 1))
00036 #if defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__)
00037
00038 #define PIN(x) ( &PORTF==&(x) ? _SFR_IO8(0x00) : (*(&x - 2)) )
00039 #else
00040 #define PIN(x) (*(&x - 2))
00041 #endif
00042
00043
00044 #if LCD_IO_MODE
00045 #define lcd_e_delay() __asm__ __volatile__( "rjmp 1f\n 1:" );
00046 #define lcd_e_high() LCD_E_PORT |= _BV(LCD_E_PIN);
00047 #define lcd_e_low() LCD_E_PORT &= ~_BV(LCD_E_PIN);
00048 #define lcd_e_toggle() toggle_e()
00049 #define lcd_rw_high() LCD_RW_PORT |= _BV(LCD_RW_PIN)
00050 #define lcd_rw_low() LCD_RW_PORT &= ~_BV(LCD_RW_PIN)
00051 #define lcd_rs_high() LCD_RS_PORT |= _BV(LCD_RS_PIN)
00052 #define lcd_rs_low() LCD_RS_PORT &= ~_BV(LCD_RS_PIN)
00053 #endif
00054
00055 #if LCD_IO_MODE
00056 #if LCD_LINES==1
00057 #define LCD_FUNCTION_DEFAULT LCD_FUNCTION_4BIT_1LINE
00058 #else
00059 #define LCD_FUNCTION_DEFAULT LCD_FUNCTION_4BIT_2LINES
00060 #endif
00061 #else
00062 #if LCD_LINES==1
00063 #define LCD_FUNCTION_DEFAULT LCD_FUNCTION_8BIT_1LINE
00064 #else
00065 #define LCD_FUNCTION_DEFAULT LCD_FUNCTION_8BIT_2LINES
00066 #endif
00067 #endif
00068
00069 #if LCD_CONTROLLER_KS0073
00070 #if LCD_LINES==4
00071
00072 #define KS0073_EXTENDED_FUNCTION_REGISTER_ON 0x24
00073 #define KS0073_EXTENDED_FUNCTION_REGISTER_OFF 0x20
00074 #define KS0073_4LINES_MODE 0x09
00075
00076 #endif
00077 #endif
00078
00079
00080
00081
00082 #if LCD_IO_MODE
00083 static void toggle_e(void);
00084 #endif
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095 static inline void _delayFourCycles(unsigned int __count)
00096 {
00097 if ( __count == 0 )
00098 __asm__ __volatile__( "rjmp 1f\n 1:" );
00099 else
00100 __asm__ __volatile__ (
00101 "1: sbiw %0,1" "\n\t"
00102 "brne 1b"
00103 : "=w" (__count)
00104 : "0" (__count)
00105 );
00106 }
00107
00108
00109
00110
00111
00112
00113 #define delay(us) _delayFourCycles( ( ( 1*(XTAL/4000) )*us)/1000 )
00114
00115
00116 #if LCD_IO_MODE
00117
00118 static void toggle_e(void)
00119 {
00120 lcd_e_high();
00121 lcd_e_delay();
00122 lcd_e_low();
00123 }
00124 #endif
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134 #if LCD_IO_MODE
00135 static void lcd_write(uint8_t data,uint8_t rs)
00136 {
00137 unsigned char dataBits ;
00138
00139
00140 if (rs) {
00141 lcd_rs_high();
00142 } else {
00143 lcd_rs_low();
00144 }
00145 lcd_rw_low();
00146
00147 if ( ( &LCD_DATA0_PORT == &LCD_DATA1_PORT) && ( &LCD_DATA1_PORT == &LCD_DATA2_PORT ) && ( &LCD_DATA2_PORT == &LCD_DATA3_PORT )
00148 && (LCD_DATA0_PIN == 0) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3) )
00149 {
00150
00151 DDR(LCD_DATA0_PORT) |= 0x0F;
00152
00153
00154 dataBits = LCD_DATA0_PORT & 0xF0;
00155 LCD_DATA0_PORT = dataBits |((data>>4)&0x0F);
00156 lcd_e_toggle();
00157
00158
00159 LCD_DATA0_PORT = dataBits | (data&0x0F);
00160 lcd_e_toggle();
00161
00162
00163 LCD_DATA0_PORT = dataBits | 0x0F;
00164 }
00165 else
00166 {
00167
00168 DDR(LCD_DATA0_PORT) |= _BV(LCD_DATA0_PIN);
00169 DDR(LCD_DATA1_PORT) |= _BV(LCD_DATA1_PIN);
00170 DDR(LCD_DATA2_PORT) |= _BV(LCD_DATA2_PIN);
00171 DDR(LCD_DATA3_PORT) |= _BV(LCD_DATA3_PIN);
00172
00173
00174 LCD_DATA3_PORT &= ~_BV(LCD_DATA3_PIN);
00175 LCD_DATA2_PORT &= ~_BV(LCD_DATA2_PIN);
00176 LCD_DATA1_PORT &= ~_BV(LCD_DATA1_PIN);
00177 LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN);
00178 if(data & 0x80) LCD_DATA3_PORT |= _BV(LCD_DATA3_PIN);
00179 if(data & 0x40) LCD_DATA2_PORT |= _BV(LCD_DATA2_PIN);
00180 if(data & 0x20) LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN);
00181 if(data & 0x10) LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN);
00182 lcd_e_toggle();
00183
00184
00185 LCD_DATA3_PORT &= ~_BV(LCD_DATA3_PIN);
00186 LCD_DATA2_PORT &= ~_BV(LCD_DATA2_PIN);
00187 LCD_DATA1_PORT &= ~_BV(LCD_DATA1_PIN);
00188 LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN);
00189 if(data & 0x08) LCD_DATA3_PORT |= _BV(LCD_DATA3_PIN);
00190 if(data & 0x04) LCD_DATA2_PORT |= _BV(LCD_DATA2_PIN);
00191 if(data & 0x02) LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN);
00192 if(data & 0x01) LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN);
00193 lcd_e_toggle();
00194
00195
00196 LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN);
00197 LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN);
00198 LCD_DATA2_PORT |= _BV(LCD_DATA2_PIN);
00199 LCD_DATA3_PORT |= _BV(LCD_DATA3_PIN);
00200 }
00201 }
00202 #else
00203 #define lcd_write(d,rs) if (rs) *(volatile uint8_t*)(LCD_IO_DATA) = d; else *(volatile uint8_t*)(LCD_IO_FUNCTION) = d;
00204
00205
00206 #endif
00207
00208
00209
00210
00211
00212
00213
00214
00215 #if LCD_IO_MODE
00216 static uint8_t lcd_read(uint8_t rs)
00217 {
00218 uint8_t data;
00219
00220
00221 if (rs)
00222 lcd_rs_high();
00223 else
00224 lcd_rs_low();
00225 lcd_rw_high();
00226
00227 if ( ( &LCD_DATA0_PORT == &LCD_DATA1_PORT) && ( &LCD_DATA1_PORT == &LCD_DATA2_PORT ) && ( &LCD_DATA2_PORT == &LCD_DATA3_PORT )
00228 && ( LCD_DATA0_PIN == 0 )&& (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3) )
00229 {
00230 DDR(LCD_DATA0_PORT) &= 0xF0;
00231
00232 lcd_e_high();
00233 lcd_e_delay();
00234 data = PIN(LCD_DATA0_PORT) << 4;
00235 lcd_e_low();
00236
00237 lcd_e_delay();
00238
00239 lcd_e_high();
00240 lcd_e_delay();
00241 data |= PIN(LCD_DATA0_PORT)&0x0F;
00242 lcd_e_low();
00243 }
00244 else
00245 {
00246
00247 DDR(LCD_DATA0_PORT) &= ~_BV(LCD_DATA0_PIN);
00248 DDR(LCD_DATA1_PORT) &= ~_BV(LCD_DATA1_PIN);
00249 DDR(LCD_DATA2_PORT) &= ~_BV(LCD_DATA2_PIN);
00250 DDR(LCD_DATA3_PORT) &= ~_BV(LCD_DATA3_PIN);
00251
00252
00253 lcd_e_high();
00254 lcd_e_delay();
00255 data = 0;
00256 if ( PIN(LCD_DATA0_PORT) & _BV(LCD_DATA0_PIN) ) data |= 0x10;
00257 if ( PIN(LCD_DATA1_PORT) & _BV(LCD_DATA1_PIN) ) data |= 0x20;
00258 if ( PIN(LCD_DATA2_PORT) & _BV(LCD_DATA2_PIN) ) data |= 0x40;
00259 if ( PIN(LCD_DATA3_PORT) & _BV(LCD_DATA3_PIN) ) data |= 0x80;
00260 lcd_e_low();
00261
00262 lcd_e_delay();
00263
00264
00265 lcd_e_high();
00266 lcd_e_delay();
00267 if ( PIN(LCD_DATA0_PORT) & _BV(LCD_DATA0_PIN) ) data |= 0x01;
00268 if ( PIN(LCD_DATA1_PORT) & _BV(LCD_DATA1_PIN) ) data |= 0x02;
00269 if ( PIN(LCD_DATA2_PORT) & _BV(LCD_DATA2_PIN) ) data |= 0x04;
00270 if ( PIN(LCD_DATA3_PORT) & _BV(LCD_DATA3_PIN) ) data |= 0x08;
00271 lcd_e_low();
00272 }
00273 return data;
00274 }
00275 #else
00276 #define lcd_read(rs) (rs) ? *(volatile uint8_t*)(LCD_IO_DATA+LCD_IO_READ) : *(volatile uint8_t*)(LCD_IO_FUNCTION+LCD_IO_READ)
00277
00278
00279 #endif
00280
00281
00282
00283
00284
00285 static uint8_t lcd_waitbusy(void)
00286
00287 {
00288 register uint8_t c;
00289
00290
00291 while ( (c=lcd_read(0)) & (1<<LCD_BUSY)) {}
00292
00293
00294 delay(2);
00295
00296
00297 return (lcd_read(0));
00298
00299 }
00300
00301
00302
00303
00304
00305
00306 static inline void lcd_newline(uint8_t pos)
00307 {
00308 register uint8_t addressCounter;
00309
00310
00311 #if LCD_LINES==1
00312 addressCounter = 0;
00313 #endif
00314 #if LCD_LINES==2
00315 if ( pos < (LCD_START_LINE2) )
00316 addressCounter = LCD_START_LINE2;
00317 else
00318 addressCounter = LCD_START_LINE1;
00319 #endif
00320 #if LCD_LINES==4
00321 #if KS0073_4LINES_MODE
00322 if ( pos < LCD_START_LINE2 )
00323 addressCounter = LCD_START_LINE2;
00324 else if ( (pos >= LCD_START_LINE2) && (pos < LCD_START_LINE3) )
00325 addressCounter = LCD_START_LINE3;
00326 else if ( (pos >= LCD_START_LINE3) && (pos < LCD_START_LINE4) )
00327 addressCounter = LCD_START_LINE4;
00328 else
00329 addressCounter = LCD_START_LINE1;
00330 #else
00331 if ( pos < LCD_START_LINE3 )
00332 addressCounter = LCD_START_LINE2;
00333 else if ( (pos >= LCD_START_LINE2) && (pos < LCD_START_LINE4) )
00334 addressCounter = LCD_START_LINE3;
00335 else if ( (pos >= LCD_START_LINE3) && (pos < LCD_START_LINE2) )
00336 addressCounter = LCD_START_LINE4;
00337 else
00338 addressCounter = LCD_START_LINE1;
00339 #endif
00340 #endif
00341 lcd_command((1<<LCD_DDRAM)+addressCounter);
00342
00343 }
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355 void lcd_command(uint8_t cmd)
00356 {
00357 lcd_waitbusy();
00358 lcd_write(cmd,0);
00359 }
00360
00361
00362
00363
00364
00365
00366
00367 void lcd_data(uint8_t data)
00368 {
00369 lcd_waitbusy();
00370 lcd_write(data,1);
00371 }
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381 void lcd_gotoxy(uint8_t x, uint8_t y)
00382 {
00383 #if LCD_LINES==1
00384 lcd_command((1<<LCD_DDRAM)+LCD_START_LINE1+x);
00385 #endif
00386 #if LCD_LINES==2
00387 if ( y==0 )
00388 lcd_command((1<<LCD_DDRAM)+LCD_START_LINE1+x);
00389 else
00390 lcd_command((1<<LCD_DDRAM)+LCD_START_LINE2+x);
00391 #endif
00392 #if LCD_LINES==4
00393 if ( y==0 )
00394 lcd_command((1<<LCD_DDRAM)+LCD_START_LINE1+x);
00395 else if ( y==1)
00396 lcd_command((1<<LCD_DDRAM)+LCD_START_LINE2+x);
00397 else if ( y==2)
00398 lcd_command((1<<LCD_DDRAM)+LCD_START_LINE3+x);
00399 else
00400 lcd_command((1<<LCD_DDRAM)+LCD_START_LINE4+x);
00401 #endif
00402
00403 }
00404
00405
00406
00407
00408 int lcd_getxy(void)
00409 {
00410 return lcd_waitbusy();
00411 }
00412
00413
00414
00415
00416
00417 void lcd_clrscr(void)
00418 {
00419 lcd_command(1<<LCD_CLR);
00420 }
00421
00422
00423
00424
00425
00426 void lcd_home(void)
00427 {
00428 lcd_command(1<<LCD_HOME);
00429 }
00430
00431
00432
00433
00434
00435
00436
00437 void lcd_putc(char c)
00438 {
00439 uint8_t pos;
00440
00441
00442 pos = lcd_waitbusy();
00443 if (c=='\n')
00444 {
00445 lcd_newline(pos);
00446 }
00447 else
00448 {
00449 #if LCD_WRAP_LINES==1
00450 #if LCD_LINES==1
00451 if ( pos == LCD_START_LINE1+LCD_DISP_LENGTH ) {
00452 lcd_write((1<<LCD_DDRAM)+LCD_START_LINE1,0);
00453 }
00454 #elif LCD_LINES==2
00455 if ( pos == LCD_START_LINE1+LCD_DISP_LENGTH ) {
00456 lcd_write((1<<LCD_DDRAM)+LCD_START_LINE2,0);
00457 }else if ( pos == LCD_START_LINE2+LCD_DISP_LENGTH ){
00458 lcd_write((1<<LCD_DDRAM)+LCD_START_LINE1,0);
00459 }
00460 #elif LCD_LINES==4
00461 if ( pos == LCD_START_LINE1+LCD_DISP_LENGTH ) {
00462 lcd_write((1<<LCD_DDRAM)+LCD_START_LINE2,0);
00463 }else if ( pos == LCD_START_LINE2+LCD_DISP_LENGTH ) {
00464 lcd_write((1<<LCD_DDRAM)+LCD_START_LINE3,0);
00465 }else if ( pos == LCD_START_LINE3+LCD_DISP_LENGTH ) {
00466 lcd_write((1<<LCD_DDRAM)+LCD_START_LINE4,0);
00467 }else if ( pos == LCD_START_LINE4+LCD_DISP_LENGTH ) {
00468 lcd_write((1<<LCD_DDRAM)+LCD_START_LINE1,0);
00469 }
00470 #endif
00471 lcd_waitbusy();
00472 #endif
00473 lcd_write(c, 1);
00474 }
00475
00476 }
00477
00478
00479
00480
00481
00482
00483
00484 void lcd_puts(const char *s)
00485
00486 {
00487 register char c;
00488
00489 while ( (c = *s++) ) {
00490 lcd_putc(c);
00491 }
00492
00493 }
00494
00495
00496
00497
00498
00499
00500
00501 void lcd_puts_p(const char *progmem_s)
00502
00503 {
00504 register char c;
00505
00506 while ( (c = pgm_read_byte(progmem_s++)) ) {
00507 lcd_putc(c);
00508 }
00509
00510 }
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521 void lcd_init(uint8_t dispAttr)
00522 {
00523 #if LCD_IO_MODE
00524
00525
00526
00527
00528 if ( ( &LCD_DATA0_PORT == &LCD_DATA1_PORT) && ( &LCD_DATA1_PORT == &LCD_DATA2_PORT ) && ( &LCD_DATA2_PORT == &LCD_DATA3_PORT )
00529 && ( &LCD_RS_PORT == &LCD_DATA0_PORT) && ( &LCD_RW_PORT == &LCD_DATA0_PORT) && (&LCD_E_PORT == &LCD_DATA0_PORT)
00530 && (LCD_DATA0_PIN == 0 ) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3)
00531 && (LCD_RS_PIN == 4 ) && (LCD_RW_PIN == 5) && (LCD_E_PIN == 6 ) )
00532 {
00533
00534 DDR(LCD_DATA0_PORT) |= 0x7F;
00535 }
00536 else if ( ( &LCD_DATA0_PORT == &LCD_DATA1_PORT) && ( &LCD_DATA1_PORT == &LCD_DATA2_PORT ) && ( &LCD_DATA2_PORT == &LCD_DATA3_PORT )
00537 && (LCD_DATA0_PIN == 0 ) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3) )
00538 {
00539
00540 DDR(LCD_DATA0_PORT) |= 0x0F;
00541 DDR(LCD_RS_PORT) |= _BV(LCD_RS_PIN);
00542 DDR(LCD_RW_PORT) |= _BV(LCD_RW_PIN);
00543 DDR(LCD_E_PORT) |= _BV(LCD_E_PIN);
00544 }
00545 else
00546 {
00547
00548 DDR(LCD_RS_PORT) |= _BV(LCD_RS_PIN);
00549 DDR(LCD_RW_PORT) |= _BV(LCD_RW_PIN);
00550 DDR(LCD_E_PORT) |= _BV(LCD_E_PIN);
00551 DDR(LCD_DATA0_PORT) |= _BV(LCD_DATA0_PIN);
00552 DDR(LCD_DATA1_PORT) |= _BV(LCD_DATA1_PIN);
00553 DDR(LCD_DATA2_PORT) |= _BV(LCD_DATA2_PIN);
00554 DDR(LCD_DATA3_PORT) |= _BV(LCD_DATA3_PIN);
00555 }
00556 delay(16000);
00557
00558
00559 LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN);
00560 LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN);
00561 lcd_e_toggle();
00562 delay(4992);
00563
00564
00565 lcd_e_toggle();
00566 delay(64);
00567
00568
00569 lcd_e_toggle();
00570 delay(64);
00571
00572
00573 LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN);
00574 lcd_e_toggle();
00575 delay(64);
00576
00577
00578 #else
00579
00580
00581
00582
00583
00584 MCUCR = _BV(SRE) | _BV(SRW);
00585
00586
00587 delay(16000);
00588 lcd_write(LCD_FUNCTION_8BIT_1LINE,0);
00589 delay(4992);
00590 lcd_write(LCD_FUNCTION_8BIT_1LINE,0);
00591 delay(64);
00592 lcd_write(LCD_FUNCTION_8BIT_1LINE,0);
00593 delay(64);
00594 #endif
00595
00596 #if KS0073_4LINES_MODE
00597
00598 lcd_command(KS0073_EXTENDED_FUNCTION_REGISTER_ON);
00599 lcd_command(KS0073_4LINES_MODE);
00600 lcd_command(KS0073_EXTENDED_FUNCTION_REGISTER_OFF);
00601 #else
00602 lcd_command(LCD_FUNCTION_DEFAULT);
00603 #endif
00604 lcd_command(LCD_DISP_OFF);
00605 lcd_clrscr();
00606 lcd_command(LCD_MODE_DEFAULT);
00607 lcd_command(dispAttr);
00608
00609 }